#include "slave.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "trace_out.h"
#include "scheduler.h"
#include <stdio.h>
#if defined(TARG_SW5)||defined(TARG_SW9)
#include <stdbool.h>
#endif

__thread_local int is_file = false;
__thread_local_fix FILE* outfile;

struct thread_ctl internal_ctl ;




struct thread_ctl* thread_ctl_constructor()
{
	struct thread_ctl* self = (thread_ctl*)malloc(sizeof(thread_ctl));

    is_file = false;
	return self;
}

void thread_ctl_destruct(struct thread_ctl* self)
{
    fclose(outfile);
}

void init_trace_ctl(char*  mydir){
    slave_init_self(&internal_ctl,mydir);
}


void init_self(struct thread_ctl* self, char*  mydir){
    char filename[40]={'\0'};
	char b[6];
	int id;
	if(mydir[0] != '\0')
     {
        strcpy(filename,mydir);
        strcat(filename,"scheduler_thread_");
        printf("%s,",mydir);
        fflush(stdout);
    }else 
        strcpy(filename,"scheduler_thread_");
	id = get_my_id();
    sprintf(b, "%d", id);
	strcat(filename,b);
	strcat(filename,".csv");
	outfile = fopen(filename,"w+");
    printf("%s\n",filename);
	fflush(stdout);
	if(outfile == NULL)
    {
        printf("error on csvfile!");
        exit(1);
    }
    return;
}


FILE*  get_file_self(struct thread_ctl* self)
{
     return outfile;
}
void print( const char* fmt, ... )
{
    FILE*  out ;
    double vargflt = 0;
    int  vargint = 0;
    char* vargpch = NULL;
    char vargch = 0;
    const char* pfmt = NULL;
    va_list vp;
    out = slave_get_file();
    va_start(vp, fmt);
    pfmt = fmt;

    while(*pfmt)
    {
        if(*pfmt == '%')
        {
            switch(*(++pfmt))
            {
                case 'c':
                    vargch = va_arg(vp, int);
					fprintf(out, "%c", vargch); 
                    break;
                case 'd':
                case 'i':
                    vargint = va_arg(vp, int);
					fprintf(out, "%i", vargint); 
                    break;
                case 'f':
                    vargflt = va_arg(vp, double);
					fprintf(out, "%lf", vargflt); 
                    break;
                case 's':
                    vargpch = va_arg(vp, char*);
					fputs(vargpch, out);
                    break;
                case 'b':
                case 'B':
                    vargint = va_arg(vp, int);
					fprintf(out, "%d", vargint); 
                    break;
                case 'x':
                case 'X':
                    vargint = va_arg(vp, int);;
					fprintf(out, "%d", vargint); 
                    break;
                case '%':
					fputs("%", out);
                    break;
                default:
                    break;
            }
            pfmt++;
        }
        else
        {
		    fwrite(pfmt, sizeof(char),1,out);
            ++pfmt;
        }
   }
   va_end(vp);
}
void print_long_long(struct thread_ctl* self, long long data)
{
    FILE*  out = slave_get_file_self(self);
	fprintf(out, "%lld", data); 
	fputs("\n", out);
}

FILE*  get_file()
{
    return slave_get_file_self(&internal_ctl);
}

void print_long_long_thread_file(long long data)
{
    slave_print_long_long(&internal_ctl, data);
}

void print_to_internal_thread_file(const char* fmt, ... )
{
    FILE*  out = slave_get_file_self(&internal_ctl);

    double vargflt = 0;
    int  vargint = 0;
    char* vargpch = NULL;
    char vargch = 0;
    const char* pfmt = NULL;
    va_list vp;

    va_start(vp, fmt);
    pfmt = fmt;

    while(*pfmt)
    {
        if(*pfmt == '%')
        {
            switch(*(++pfmt))
            {
                case 'c':
                    vargch = va_arg(vp, int); 
					fprintf(out, "%c", vargch); 
                    break;
                case 'd':
                case 'i':
                    vargint = va_arg(vp, int);
					fprintf(out, "%i", vargint); 
                    break;
                case 'f':
                    vargflt = va_arg(vp, double);
					fprintf(out, "%lf", vargflt); 
                    break;
                case 's':
                    vargpch = va_arg(vp, char*);
					fputs(vargpch, out);
                    break;
                case 'b':
                case 'B':
                    vargint = va_arg(vp, int);
					fprintf(out, "%d", vargint); 
                    break;
                case 'x':
                case 'X':
                    vargint = va_arg(vp, int);
					fprintf(out, "%d", vargint); 
                    break;
                case '%':
					fputs("%", out);
                    break;
                default:
                    break;
            }
            pfmt++;
        }
        else
        {
			fwrite(pfmt, sizeof(char),1,out);
            ++pfmt;
        }
   }
   va_end(vp);
}

void end_file_spawn_self(struct thread_ctl* self)
{
    if(outfile!=NULL)
	    fputs("spawn\n", outfile);
    else
    {
        printf("error on outfile");
        fflush(stdout);
    }
}

void end_file_spawn()
{
    end_file_spawn_self(&internal_ctl);
}

